package com.study.crypto.utils;

import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.util.BigIntegers;

import java.io.IOException;
import java.math.BigInteger;

/**
 * 与 asn.1 语法相关的工具类
 *
 * @author Songjin
 * @since 2021-02-17 17:56
 */
public final class ASN1Utils {
    
    private ASN1Utils() {
    }
    
    /**
     * 将 derObjects 集合转换为 ber 编码的 ASN1Set
     *
     * @param derObjects 集合
     * @return BERSet
     */
    public static ASN1Set createBerSetFromList(ASN1Encodable... derObjects) {
        return new BERSet(createAsn1EncodableVector(derObjects));
    }
    
    /**
     * 将 derObjects 集合转换为 der 编码的 ASN1Set
     *
     * @param derObjects 集合
     * @return DERSet
     */
    public static ASN1Set createDerSetFromList(ASN1Encodable... derObjects) {
        return new DERSet(createAsn1EncodableVector(derObjects));
    }
    
    public static ASN1EncodableVector createAsn1EncodableVector(ASN1Encodable... derObjects) {
        ASN1EncodableVector v = new ASN1EncodableVector();
        for (ASN1Encodable derObject : derObjects) {
            v.add(derObject);
        }
        return v;
    }
    
    /**
     * @param algId 算法标识
     * @return 算法标识
     */
    public static AlgorithmIdentifier fixAlgID(AlgorithmIdentifier algId) {
        if (algId.getParameters() == null) {
            return new AlgorithmIdentifier(algId.getAlgorithm(), DERNull.INSTANCE);
        }
        return algId;
    }
    
    /**
     * 将 sm2 签名值拆分成 r、s 两个字节数组
     * @param signature 签名值
     * @return r、s 字节数组
     */
    public static byte[][] disassembleSignature(byte[] signature) {
        try (ASN1InputStream inputStream = new ASN1InputStream(signature)) {
            ASN1Sequence sequence = (ASN1Sequence) inputStream.readObject();
            ASN1Integer r_ = (ASN1Integer) sequence.getObjectAt(0);
            ASN1Integer s_ = (ASN1Integer) sequence.getObjectAt(1);
            byte[] r = BigIntegers.asUnsignedByteArray(r_.getPositiveValue());
            byte[] s = BigIntegers.asUnsignedByteArray(s_.getPositiveValue());
            return new byte[][]{r, s};
        } catch (IOException e) {
            throw new IllegalArgumentException("签名异常", e);
        }
    }

    /**
     * 将 sm2 签名值 R、S 组装成 ASN.1 结构
     * @param r 签名值R域
     * @param s 签名值S域
     * @return ASN.1编码字节流
     */
    public static byte[] assembleSignature(byte[] r, byte[] s) throws IOException {
        ASN1EncodableVector vector = new ASN1EncodableVector();
        vector.add(new ASN1Integer(new BigInteger(1, r)));
        vector.add(new ASN1Integer(new BigInteger(1, s)));
        DERSequence sequence = new DERSequence(vector);
        return sequence.getEncoded();
    }
}
